package org.ham007.proxysender.server.twitter.cmd;

import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.jdo.PersistenceManager;

import org.ham007.proxysender.server.PMF;
import org.ham007.proxysender.server.twitter.MyTwitter;
import org.ham007.proxysender.server.twitter.entity.LastMessageInfo;

import twitter4j.DirectMessage;
import twitter4j.Paging;
import twitter4j.Twitter;
import twitter4j.TwitterException;

/**
 * メッセージ解析、実行</br>
 * @author 223
 *
 */
public class MessageParser {

	/**
	 * 全て読み直す
	 */
	private final int ALL_REREAD = 1;
	/**
	 * 1ページのメッセージ数
	 */
	private final int ONE_PAGE_COUNT = 6;
	
	private Twitter twitter = null;
	private Logger logger = null;
	
	public MessageParser()
	{
		twitter = MyTwitter.get();
		logger = Logger.getLogger(Logger.GLOBAL_LOGGER_NAME);
}
	
	/**
	 * 処理実行
	 */
	public void proc()
	{
		List<DirectMessage> target_d_msgs = null;
		
		try
		{			
			target_d_msgs = getTargetDirectMessage();
		}
		catch(Exception e)
		{
			e.printStackTrace(System.err);
			return;
		}
		
//		System.out.println("取得したダイレクトメッセージ一覧");
		for(DirectMessage dm : target_d_msgs)
		{
//			System.out.print("    ID:" + Integer.toString(dm.getId()));
//			System.out.print("    RateLimit:" + Integer.toString(dm.getRateLimitLimit()));
//			System.out.print("    送信日付:" + dm.getCreatedAt().toString());
//			System.out.print("    送り主:" + dm.getSenderScreenName());
//			System.out.println("    メッセージ:" + dm.getText());

			try
			{
				parseAndProc(dm);
			}
			catch(Exception e)
			{
				e.printStackTrace(System.err);
			}
		}
	}
	
	/**
	 * 前回フォローユーザー情報の取得</br>
	 * 未取得時はnullを返す</br>
	 * </br>
	 * @return ユーザー情報
	 */
	private LastMessageInfo getLastFollowInfo()
	{
		LastMessageInfo last_msg = null;
		PersistenceManager pm = PMF.get().getPersistenceManager();
		
		try
		{
			last_msg = pm.getObjectById(LastMessageInfo.class, "message");
		}
		catch(Exception e)
		{
			last_msg = null;
		}
		finally
		{
			if(last_msg != null)
				pm.close();
		}
		
		return last_msg;
	}
	
	/**
	 * 前回メッセージ情報の更新
	 * @param msg_info
	 */
	private void updateLastMessageInfo(LastMessageInfo msg_info)
	{
		PersistenceManager pm = PMF.get().getPersistenceManager();
		
		try
		{
			pm.makePersistent(msg_info);
		}
		finally
		{
			pm.close();
		}
	}
	
	/**
	 * 対象のダイレクトメッセージ一覧取得</br>
	 * </br>
	 * @return
	 * @throws TwitterException
	 */
	private List<DirectMessage> getTargetDirectMessage() throws TwitterException
	{
		logger.log(Level.INFO, "start getTargetDirectMessage()");
		
		int latest_page_no = 1;
		LastMessageInfo last_msg = getLastFollowInfo();
		
		if(last_msg == null)
		{
			logger.log(Level.INFO, "get last_msg is null.");
			last_msg = new LastMessageInfo("message", ALL_REREAD);
		}
		
		if(last_msg.getMessageId() == ALL_REREAD)
		{
			logger.log(Level.INFO, "get last_msg.LastID is ALL_REREAD.");
			
			//最古ページNoを取得する。
			while(true)
			{
				Paging paging = new Paging(latest_page_no, ONE_PAGE_COUNT);
				List<DirectMessage> dms = twitter.getDirectMessages(paging);
				if(dms.size() != ONE_PAGE_COUNT)
				 	break;
				latest_page_no += 1;
			}
			
			logger.log(Level.INFO, "Reread end. latest_page_no : " + Integer.toString(latest_page_no));
		}
		else
		{
			logger.log(Level.INFO, "get last_msg.LastID is EnableID : " + Integer.toString(last_msg.getMessageId()));
			
			//未読メッセージ数を求め、ページ番号を再調整する。
			int unread_cnt = getUnreadDirectMessageCount(last_msg.getMessageId());
			latest_page_no = (int)Math.ceil(unread_cnt * 1.0 / ONE_PAGE_COUNT);
			
			logger.log(Level.INFO, "unread_cnt : " + Integer.toString(unread_cnt));
			logger.log(Level.INFO, "latest_page_no : " + Integer.toString(latest_page_no));
		}
		
		List<DirectMessage> result = new ArrayList<DirectMessage>();
		
		if(latest_page_no == 0)
			return result;
		
		//未読ダイレクトメッセージの取得
		Paging paging = new Paging(latest_page_no, ONE_PAGE_COUNT, last_msg.getMessageId());
		List<DirectMessage> dms = twitter.getDirectMessages(paging);
		
		int new_msg_id = 1;
		for (int i=dms.size()-1;i>=0;i--)
		{
			DirectMessage dm = dms.get(i);
			if(last_msg.getMessageId() <= dm.getId())
				result.add(dm);
			new_msg_id = dm.getId();
		}

		last_msg.setMessageId(new_msg_id);
		updateLastMessageInfo(last_msg);
		
		return result;
	}
	
	/**
	 * 未読ダイレクトメッセージメッセージ数取得</br>
	 * @param since_msg_id
	 * @return
	 * @throws TwitterException
	 */
	private int getUnreadDirectMessageCount(int since_msg_id) throws TwitterException
	{
		logger.log(Level.INFO, "start getUnreadDirectMessageCount()");
		
		int search_page_no = 1; 
		int unread_cnt = 0;
				
		while(true)
		{
			Paging paging = new Paging(search_page_no, ONE_PAGE_COUNT);
			List<DirectMessage> dms = twitter.getDirectMessages(paging);
			boolean msg_found = false;
			
			for(DirectMessage dm : dms)
			{
				if(dm.getId() != since_msg_id)
				{
					unread_cnt++;
				}
				else
				{
					msg_found = true;
					break;
				}
			}
			
			if(msg_found == true)
				break;
			search_page_no++;
			
			if(dms.size() != ONE_PAGE_COUNT)
				break;
		}
				
		return unread_cnt;
	}
		
	/**
	 * 解析と実行
	 * @param dm ダイレクトメッセージ
	 */
	private void parseAndProc(DirectMessage dm) throws Exception
	{
		
		List<CommandProcesser> processers = new ArrayList<CommandProcesser>();
		processers.add(new ProxySendProcesser(twitter));
		
		logger.log(Level.INFO, "start parseAndProc()");
		
		for(CommandProcesser proc : processers)
		{
			if(proc.isTarget(dm) == true)
			{
				logger.log(Level.INFO, "UsingParser : " + proc.getClass().toString());
				proc.proc(dm);
				break;
			}
		}
		
		logger.log(Level.INFO, "end parseAndProc()");
	}
}
